home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / File / Passwd / Authbasic.php next >
PHP Script  |  2004-10-01  |  11KB  |  387 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: File :: Passwd :: Authbasic                                  |
  4. // +----------------------------------------------------------------------+
  5. // | This source file is subject to version 3.0 of the PHP license,       |
  6. // | that is available at http://www.php.net/license/3_0.txt              |
  7. // | If you did not receive a copy of the PHP license and are unable      |
  8. // | to obtain it through the world-wide-web, please send a note to       |
  9. // | license@php.net so we can mail you a copy immediately.               |
  10. // +----------------------------------------------------------------------+
  11. // | Copyright (c) 2003-2004 Michael Wallner <mike@iworks.at>             |
  12. // +----------------------------------------------------------------------+
  13. //
  14. // $Id: Authbasic.php,v 1.15 2004/06/07 19:19:47 mike Exp $
  15.  
  16. /**
  17. * Manipulate AuthUserFiles as used for HTTP Basic Authentication.
  18. *
  19. * @author   Michael Wallner <mike@php.net>
  20. * @package  File_Passwd
  21. */
  22.  
  23. /**
  24. * Requires File::Passwd::Common
  25. */
  26. require_once 'File/Passwd/Common.php';
  27.  
  28. /**
  29. * Manipulate AuthUserFiles as used for HTTP Basic Authentication.
  30. *
  31. * <kbd><u>
  32. *   Usage Example:
  33. * </u></kbd>
  34. * <code>
  35. *   $htp = &File_Passwd::factory('AuthBasic');
  36. *   $htp->setMode('sha');
  37. *   $htp->setFile('/www/mike/auth/.htpasswd');
  38. *   $htp->load();
  39. *   $htp->addUser('mike', 'secret');
  40. *   $htp->save();
  41. * </code>
  42. * <kbd><u>
  43. *   Output of listUser()
  44. * </u></kbd>
  45. * <pre>
  46. *      array
  47. *       + user => crypted_passwd
  48. *       + user => crypted_passwd
  49. * </pre>
  50. * @author   Michael Wallner <mike@php.net>
  51. * @package  File_Passwd
  52. * @version  $Revision: 1.15 $
  53. * @access   public
  54. */
  55. class File_Passwd_Authbasic extends File_Passwd_Common
  56. {
  57.     /** 
  58.     * Path to AuthUserFile
  59.     *
  60.     * @var string
  61.     * @access private
  62.     */
  63.     var $_file = '.htpasswd';
  64.  
  65.     /** 
  66.     * Actual encryption mode
  67.     *
  68.     * @var string
  69.     * @access private
  70.     */
  71.     var $_mode = 'sha';
  72.  
  73.     /** 
  74.     * Supported encryption modes
  75.     *
  76.     * @var array
  77.     * @access private
  78.     */
  79.     var $_modes = array('md5' => 'm', 'des' => 'd', 'sha' => 's');
  80.  
  81.     /** 
  82.     * Constructor
  83.     * 
  84.     * @access public
  85.     * @param  string $file   path to AuthUserFile
  86.     */
  87.     function File_Passwd_Authbasic($file = '.htpasswd')
  88.     {
  89.         File_Passwd_Authbasic::__construct($file);
  90.     }
  91.  
  92.     /**
  93.     * Constructor (ZE2)
  94.     * 
  95.     * Rewritten because DES encryption is not 
  96.     * supportet by the Win32 httpd.
  97.     * 
  98.     * @access protected
  99.     * @param  string $file   path to AuthUserFile
  100.     */
  101.     function __construct($file = '.htpasswd')
  102.     {
  103.         if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
  104.             unset($this->_modes['des']);
  105.         }
  106.         $this->setFile($file);
  107.     }
  108.  
  109.     /**
  110.     * Fast authentication of a certain user
  111.     * 
  112.     * Returns a PEAR_Error if:
  113.     *   o file doesn't exist
  114.     *   o file couldn't be opened in read mode
  115.     *   o file couldn't be locked exclusively
  116.     *   o file couldn't be unlocked (only if auth fails)
  117.     *   o file couldn't be closed (only if auth fails)
  118.     *
  119.     * @static   call this method statically for a reasonable fast authentication
  120.     * 
  121.     * @throws   PEAR_Error
  122.     * @access   public
  123.     * @return   mixed   true if authenticated, false if not or PEAR_Error
  124.     * @param    string  $file   path to passwd file
  125.     * @param    string  $user   user to authenticate
  126.     * @param    string  $pass   plaintext password
  127.     * @param    string  $mode   des, sha or md5
  128.     */
  129.     function staticAuth($file, $user, $pass, $mode)
  130.     {
  131.         $line = File_Passwd_Common::_auth($file, $user);
  132.         if (!$line || PEAR::isError($line)) {
  133.             return $line;
  134.         }
  135.         list(,$real)    = explode(':', $line);
  136.         $crypted        = File_Passwd_Authbasic::_genPass($pass, $real, $mode);
  137.         if (PEAR::isError($crypted)) {
  138.             return $crypted;
  139.         }
  140.         return ($real === $crypted);
  141.     }
  142.     
  143.     /** 
  144.     * Apply changes and rewrite AuthUserFile
  145.     *
  146.     * Returns a PEAR_Error if:
  147.     *   o directory in which the file should reside couldn't be created
  148.     *   o file couldn't be opened in write mode
  149.     *   o file couldn't be locked exclusively
  150.     *   o file couldn't be unlocked
  151.     *   o file couldn't be closed
  152.     * 
  153.     * @throws PEAR_Error
  154.     * @access public
  155.     * @return mixed true on success or PEAR_Error
  156.     */
  157.     function save()
  158.     {
  159.         $content = '';
  160.         foreach ($this->_users as $user => $pass) {
  161.             $content .= $user . ':' . $pass . "\n";
  162.         }
  163.         return $this->_save($content);
  164.     }
  165.  
  166.     /** 
  167.     * Add an user
  168.     *
  169.     * The username must start with an alphabetical character and must NOT
  170.     * contain any other characters than alphanumerics, the underline and dash.
  171.     * 
  172.     * Returns a PEAR_Error if:
  173.     *   o user already exists
  174.     *   o user contains illegal characters
  175.     * 
  176.     * @throws PEAR_Error
  177.     * @access public
  178.     * @return mixed true on success or PEAR_Error
  179.     * @param string $user
  180.     * @param string $pass
  181.     */
  182.     function addUser($user, $pass)
  183.     {
  184.         if ($this->userExists($user)) {
  185.             return PEAR::raiseError(
  186.                 sprintf(FILE_PASSWD_E_EXISTS_ALREADY_STR, 'User ', $user),
  187.                 FILE_PASSWD_E_EXISTS_ALREADY
  188.             );
  189.         }
  190.         if (!preg_match($this->_pcre, $user)) {
  191.             return PEAR::raiseError(
  192.                 sprintf(FILE_PASSWD_E_INVALID_CHARS_STR, 'User ', $user),
  193.                 FILE_PASSWD_E_INVALID_CHARS
  194.             );
  195.         }
  196.         $this->_users[$user] = $this->_genPass($pass);
  197.         return true;
  198.     }
  199.  
  200.     /** 
  201.     * Change the password of a certain user
  202.     *
  203.     * Returns a PEAR_Error if user doesn't exist.
  204.     * 
  205.     * @throws PEAR_Error
  206.     * @access public
  207.     * @return mixed true on success or a PEAR_Error
  208.     * @param string $user   the user whose password should be changed
  209.     * @param string $pass   the new plaintext password
  210.     */
  211.     function changePasswd($user, $pass)
  212.     {
  213.         if (!$this->userExists($user)) {
  214.             return PEAR::raiseError(
  215.                 sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
  216.                 FILE_PASSWD_E_EXISTS_NOT
  217.             );
  218.         }
  219.         $this->_users[$user] = $this->_genPass($pass);
  220.         return true;
  221.     }
  222.  
  223.     /** 
  224.     * Verify password
  225.     *
  226.     * Returns a PEAR_Error if:
  227.     *   o user doesn't exist
  228.     *   o an invalid encryption mode was supplied
  229.     * 
  230.     * @throws PEAR_Error
  231.     * @access public
  232.     * @return mixed true if passwords equal, false if they don't, or PEAR_Error
  233.     * @param string $user   the user whose password should be verified
  234.     * @param string $pass   the plaintext password to verify
  235.     */
  236.     function verifyPasswd($user, $pass)
  237.     {
  238.         if (!$this->userExists($user)) {
  239.             return PEAR::raiseError(
  240.                 sprintf(FILE_PASSWD_E_EXISTS_NOT_STR, 'User ', $user),
  241.                 FILE_PASSWD_E_EXISTS_NOT
  242.             );
  243.         }
  244.         $real = $this->_users[$user];
  245.         return ($real === $this->_genPass($pass, $real));
  246.     }
  247.  
  248.     /** 
  249.     * Get actual encryption mode
  250.     *
  251.     * @access public
  252.     * @return string
  253.     */
  254.     function getMode()
  255.     {
  256.         return $this->_mode;
  257.     }
  258.  
  259.     /** 
  260.     * Get supported encryption modes
  261.     *
  262.     * <pre>
  263.     *   array
  264.     *    + md5
  265.     *    + sha
  266.     *    + des
  267.     * </pre>
  268.     * 
  269.     * ATTN: DES encryption not available on Win32!
  270.     * 
  271.     * @access public
  272.     * @return array
  273.     */
  274.     function listModes()
  275.     {
  276.         return array_keys($this->_modes);
  277.     }
  278.  
  279.     /** 
  280.     * Set the encryption mode
  281.     *
  282.     * You can choose one of md5, sha or des.
  283.     * 
  284.     * ATTN: DES encryption not available on Win32!
  285.     * 
  286.     * Returns a PEAR_Error if a specific encryption mode is not supported.
  287.     * 
  288.     * @throws PEAR_Error
  289.     * @access public
  290.     * @return mixed true on succes or PEAR_Error
  291.     * @param string $mode
  292.     */
  293.     function setMode($mode)
  294.     {
  295.         $mode = strToLower($mode);
  296.         if (!isset($this->_modes[$mode])) {
  297.             return PEAR::raiseError(
  298.                 sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $this->_mode),
  299.                 FILE_PASSWD_E_INVALID_ENC_MODE
  300.             );
  301.         }
  302.         $this->_mode = $mode;
  303.         return true;
  304.     }
  305.  
  306.     /**
  307.     * Generate password with htpasswd executable
  308.     * 
  309.     * @access   private
  310.     * @return   string  the crypted password
  311.     * @param    string  $pass   the plaintext password
  312.     * @param    string  $salt   the salt to use
  313.     * @param    string  $mode   encyption mode, usually determined from
  314.     *                           <var>$this->_mode</var>
  315.     */
  316.     function _genPass($pass, $salt = null, $mode = null)
  317.     {
  318.         $mode = is_null($mode) ? strToLower($this->_mode) : strToLower($mode);
  319.  
  320.         if ($mode == 'md5') {
  321.             return File_Passwd::crypt_apr_md5($pass, $salt);
  322.         } elseif ($mode == 'des') {
  323.             return File_Passwd::crypt_des($pass, $salt);
  324.         } elseif ($mode == 'sha') {
  325.             return File_Passwd::crypt_sha($pass, $salt);
  326.         }
  327.         
  328.         return PEAR::raiseError(
  329.             sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
  330.             FILE_PASSWD_E_INVALID_ENC_MODE                
  331.         );
  332.     }
  333.     
  334.     /** 
  335.     * Parse the AuthUserFile
  336.     * 
  337.     * Returns a PEAR_Error if AuthUserFile has invalid format.
  338.     *
  339.     * @throws PEAR_Error
  340.     * @access public
  341.     * @return mixed true on success or PEAR_error
  342.     */
  343.     function parse()
  344.     {
  345.         $this->_users = array();
  346.         foreach ($this->_contents as $line) {
  347.             $user = explode(':', $line);
  348.             if (count($user) != 2) {
  349.                 return PEAR::raiseError(
  350.                     FILE_PASSWD_E_INVALID_FORMAT_STR,
  351.                     FILE_PASSWD_E_INVALID_FORMAT
  352.                 );
  353.             }
  354.             $this->_users[$user[0]] = trim($user[1]);
  355.         }
  356.         $this->_contents = array();
  357.         return true;
  358.     }
  359.     
  360.     /**
  361.     * Generate Password
  362.     * 
  363.     * Returns PEAR_Error FILE_PASSD_E_INVALID_ENC_MODE if the supplied
  364.     * encryption mode is not supported.
  365.     *
  366.     * @static
  367.     * @access   public
  368.     * @return   mixed   The crypted password on success or PEAR_Error on failure.
  369.     * @param    string  $pass The plaintext password.
  370.     * @param    string  $mode The encryption mode to use (des|md5|sha).
  371.     * @param    string  $salt The salt to use.
  372.     */
  373.     function generatePassword($pass, $mode = FILE_PASSWD_DES, $salt = null)
  374.     {
  375.         if (!in_array(strToLower($mode), array('des', 'md5', 'sha'))) {
  376.             return PEAR::raiseError(
  377.                 sprintf(FILE_PASSWD_E_INVALID_ENC_MODE_STR, $mode),
  378.                 FILE_PASSWD_E_INVALID_ENC_MODE                
  379.             );
  380.         }
  381.         return File_Passwd_Authbasic::_genPass($pass, $salt, $mode);
  382.     }
  383.     
  384. }
  385. ?>